/*****************************************************************************
*    Ali Corp. All Rights Reserved. 2007 Copyright (C)
*
*    File:    slot.S
*
*    Description:    This file contains all code in standby mode.
*    History:
*           Date            Athor        Version          Reason
*	    ============	=============	=========	=================
*	1.	05.22.2007       zhaojian tang      Ver 0.1    Create file.
*	2.	28.03.2008		 Victor				Ver	0.2	 Support 16515 VFD panel
*****************************************************************************/
#include <hal/mips.h>
#include <hld/pan/pan.h>
#include <sys_config.h>


#define SYS_IC_NB_BASE_H		0xb800
#define SYS_IC_NB_EISR			0x30
#define SYS_IC_SB_IRC_BITIE 	0x80000

#define COM_VERSION			0x00
#define SDRAM_ASR			0x04	// 16bits. 0x84-0x85: SDRAM ASR; 0x86-0x87:reserved
#define SDRAM_MSR			0x08	// 16bits. 0x88-0x89: SDRAM MSR; 0x8A-0x8B:reserved
#define FLASH_CTRL1			0x0C	// 32bits. sflash ctrl interface
#define FLASH_MCR1			0x10	// 32bits. flash memory control reg
#define FLASH_CTRL2			0x14	// 32bits. sflash ctrl interface
#define FLASH_MCR2			0x18	// 32bits. flash memory control reg
#define BOOT_LOGO			0x1C	// 16bits. 
			# onoff:bit 15		1:on / 0:off
			# tv format:bit 12~14	0:PAL / 1:NTSC / 2:PAL_M / 3:PAL_N / 4:PAL_60 / 5:NTSC_443
			# source picture height:bit 0~11
			# For example : if open logo in bootload, and display format is PAL, and source picture is 480, then it should be set to 0x81e0.
#define CRYSTAL_TYPE		0x1E	// 8bit. 0:27M; 1:13.5M
#define PAN_TYPE			0x1F	// 3bits.[bit7-bit5] 0:hwscan; 1:compan
#define PAN_TYPE_MASK		0xE0
#define DVBC_SUPPORT		0x1F	// 2bit.[bit4-bit3]. 0:DVBS; 1:DVBC/DVBT;
#define DVBC_SUPPORT_MASK 0x18
#define NEC_INVERT			0x1F	// 1bit.[bit2]. 1:support nec invert ir; 0: not suppurt nec invert ir
#define NEC_INVERT_MASK		0x04
#define CHIP_BONDING		0x20	// 8bit.
			# [bit7-bit3: 0], [bit2-bit0: bonding option]
			# bit2: 1 - M3602/M3381, 0 - M3601c/M3381c
			# bit1: 0 - M3601c old IC, 1 - M3601c/M3381c new IC with bonding
			# bit0: 0 - M3601C(D), 1 - M3381C(D)

#define EXT_VERSION			0x80	// 2bytes
#define	PAN_HW_INFO_BASE	0x84	// 60bytes.	reference struct pan_hw_info
#define STBY_PAN_TYPE		0xC0	// 1byte 	1--show timer; 2--show off; 3--show blank
#define BOOT_TYPE			0xC1	// 1bit.[bit7]	0:bootup; 1:enter into standby after cold boot.
#define BOOT_TYPE_MASK		0x80
#define PAN_KEY_NUM			0xC1	// 3bits.[bit6-bit4] 0:one panel standby key; 1:two key; other: not define now
#define PAN_KEY_NUM_MASK	0x70
#define IRP_KEY_NUM			0xC1	// 4bits.[bit3-bit0] 0:one ir standby key; 1:two key; 2:three key; 3: four key; other: not define now
#define IRP_KEY_NUM_MASK	0x0F
#define LED_ARRAY_BASE		0xD0	// 16bytes.	'0','1','2','3','4','5','6','7','8','9','o','F',':','-','_',' '

#define IRP_KEY_STANDBY1	0x100
#define IRP_KEY_STANDBY2	0x104
#define IRP_KEY_STANDBY3	0x108
#define IRP_KEY_STANDBY4	0x10C
#define PAN_KEY_STANDBY1	0x110
#define PAN_KEY_STANDBY2	0x114
#define PAN_KEY_STANDBY3	0x118
#define PAN_KEY_STANDBY4	0x11C


#define TIMER_COMPARE_1S	(27000000 / 4)

# MACRO: bin2ascii(reg b1, reg d1)
#  reg b1: Input binary data.
#  reg d1: Output BCD code data.
# Internal:
#  t0: ;
#  t1: Primary higher 4 digital;
#  t2: Lower 4 bit digital;
#  t3: ;
#
		.macro	bin2ascii b1,d1
		andi	t0, \b1, 0xf0;
		srl		t0, 4;					# 6bits->2bits higher
		srl		t1, t0, 1;
		addu	t1, t0;					# Get the base: 00b=>0d, 01b=>1d, 10b=>3d, 11b=>4d
		sll		t2, t1, 3;
		sll		t3, t1, 1;
		addu	t3, t2;					# 10X: 0=>0, 1=>10, 2=>20, etc...
		subu	t2, \b1, t3;			# Get draft lower value to t2
		li		t0, 10;
		blt		t2, t0, 11f;			# If lower 4bits<10, finished
		nop
		addiu	t1, 1;					# Else higher+1, and lower-10.
		sub		t2, t0;
		blt		t2, t0, 11f;			# If lower 4bits<10, finished
		nop
		addiu	t1, 1;					# Else higher+1, and lower-10.
		sub		t2, t0;
11:		sll		t1, 4;
		or		\d1, t1, t2;
		.endm

# MACRO: get_led_array(reg dr, reg base)
#	reg dr: load led_array to dr.
#	reg base: address of "boot.cfg" in flash
		.macro	get_led_array dr, base
		addi	\dr, \base, LED_ARRAY_BASE
		.endm

# MACRO: get_ir_power_key_num(reg dr)
#	reg dr: load ir power key number to dr.
#	reg base: address of "boot.cfg" in flash
		.macro	get_ir_power_key_num dr, base
		lb		\dr, IRP_KEY_NUM(\base)
		andi	\dr, IRP_KEY_NUM_MASK
		.endm

# MACRO: get_fp_power_key_num(reg dr)
#	reg dr: load fp power key number to dr.
#	reg base: address of "boot.cfg" in flash
		.macro	get_fp_power_key_num dr, base
		lb		\dr, PAN_KEY_NUM(\base)
		andi	\dr, PAN_KEY_NUM_MASK
		srl     \dr, \dr, 4
		.endm
				
# MACRO: get_ir_power_key(reg dr, reg index, reg base)
#	reg dr: load No. index ir power key to dr.
#	reg base: address of "boot.cfg" in flash
		.macro	get_ir_power_key dr, index, base
		beq		\index, 0, 90f
		nop
		beq		\index, 1, 91f
		nop
		beq		\index, 2, 92f
		nop
93:
		lw		\dr, IRP_KEY_STANDBY4(\base)	# get ir standby key 4
		b		99f
		nop
92:
		lw		\dr, IRP_KEY_STANDBY3(\base)	# get ir standby key 3
		b		99f
		nop
91:
		lw		\dr, IRP_KEY_STANDBY2(\base)	# get ir standby key 2
		b		99f
		nop
90:		
		lw		\dr, IRP_KEY_STANDBY1(\base)	# get ir standby key 1
99:		
		.endm
		
# MACRO: get_fp_power_key(reg dr, reg index, reg base)
#	reg dr: load No. index fp power key to dr.
#	reg base: address of "boot.cfg" in flash
		.macro	get_fp_power_key dr, index, base
		beq		\index, 0, 90f
		nop
		beq		\index, 1, 91f
		nop
		beq		\index, 2, 92f
		nop
93:
		lw		\dr, PAN_KEY_STANDBY4(\base)	# get pan standby key 4
		b		99f
		nop		
92:		
		lw		\dr, PAN_KEY_STANDBY3(\base)	# get pan standby key 3
		b		99f
		nop		
91:		
		lw		\dr, PAN_KEY_STANDBY2(\base)	# get pan standby key 2
		b		99f
		nop		
90:
		lw		\dr, PAN_KEY_STANDBY1(\base)	# get pan standby key 1
99:
		.endm


# MACRO: get_pan_hw_info(reg dr, reg base)
#	reg dr: load pan_hw_info to dr.
#	reg base: address of "boot.cfg" in flash
		.macro	get_pan_hw_info dr, base
		addi	\dr, \base, PAN_HW_INFO_BASE
		.endm

# MACRO: gettimerdata(reg sr)
#  reg dr: get timefield to dr
#
		.macro	gettimerdata dr
		li		t1, 0x80000700
		lw		\dr, 0(t1)
		.endm

# MACRO: settimerdata(reg sr)
#  reg dr: set sr(time) to  timefield.
#
		.macro	settimerdata sr
		li		t1, 0x80000700
		sw		\sr,0(t1)	
		.endm


#if (defined(PAN_HW_KEY_DATA_POLAR) && defined(PAN_HW_SCAN_CLOCK))
#define PAN_HW_INIT_PARAM	(1 | (1 << 1) | (PAN_HW_KEY_DATA_POLAR << 2) | \
							 (PAN_HW_SCAN_CLOCK << 3))
#endif


#--------------------------------------------------------------------
#
#   Function_Name: sys_preboot
#     This function used only for board dedicated issue patch, just as
#     turn off LED GPIO, if you want do other patch about chipset,
#     please added into _Init_Chipset in boot.S.
#--------------------------------------------------------------------
		.globl  sys_preboot
		.ent	sys_preboot
		.set noreorder
sys_preboot:
		jr		ra
		nop
		.set 	reorder
		.end	sys_preboot



		.globl  sys_prestandby
		.ent	sys_prestandby
		.set	noreorder
sys_prestandby:
		move	k0, ra
		nop
		jal		ini_ir					# Init IR
		nop

        jal     init_gpio               ##Init GPIO for panel
        nop
        
		jal		get_boot_cfg_addr
		nop
		move	k1, v0					# k1: address of "boot.cfg" data

		get_pan_hw_info a0, k1
		
		jal 	pan_hwscan_init
#ifdef PAN_HW_INIT_PARAM
		li		a1, PAN_HW_INIT_PARAM
#else
		li		a1, 1
#endif
		move	s8, zero				# Preset led_buff(s8) as 0
		get_pan_hw_info t8, k1
		lb		t0, 0(t8)				# Check kb_type
		andi	t0, 0x02		
		bne 	t0, zero, 1f
		nop
# type_kb&0x02==0: LED PIN is not controlled by shifter		
		lhu		a0, 30(t8)
		li		a1, 1		

		jal 	pan_hwscan_gpio_set_bit		# Set STANDBY to valid status
		nop

		b		2f
		nop

# type_kb&0x02==1: LED PIN is controlled by shifter	
1:
		li		t1, 0				# Setup led_buff to invalidate status but STANDBY
		li		t2, 4
		addi		t8, 30
ledbufbit:
		lhu		t0, 0(t8)				
		srl 	t3, t0, 2				# Get the ledbit position
		andi	t3, 0x7
		li		t4, 1
		sll 	t4, t3					# Bit mask
		andi	t3, t0, 1				# Check bit active status
		bne 	t3, zero, ledposbit
		nop
		or		s8, t4					# Merge this bit
ledposbit:
		addi	t1, 1	
		addi	t8, 2						# Next PIN
		bne 	t1, t2, ledbufbit
		nop
		andi	s8, 0xff
2:

		move	ra, k0
		
		lb		t1, STBY_PAN_TYPE(k1)		
		beq		t1, 0, 0f			# 0--show "----"	
		nop
		beq		t1, 1, 1f			# 1--show timer
		nop
		beq		t1, 2, 2f			# 2--show "off "
		nop
		beq		t1, 3, 3f			# 3--show blank
		nop
		b		5f
		nop
0:
		li		s6, 0xdddd			# "----" index
		b		5f
		nop
1:
		li		t0, (0x1f<<12)			# Hour in ASCII
		and 	v0, t0, s5
		srl 	v0, 12
		bin2ascii v0, t5
		sll 	t5, 8
		li		t0,(0x3f<<6)			# Minute in ASCII
		and 	v0, t0, s5
		srl 	v0, 6
		bin2ascii v0, t4
		or		s6, t4, t5		
		settimerdata s6
		b		5f
		nop
2:
		li		s6, 0xabbf				# "OFF " index
		b		5f
		nop
3:
		li		s6, 0xffff				# "    " index
5:
		jr		ra
		nop
		.set reorder
		.end sys_prestandby


		.globl	sys_poststandby
		.ent	sys_poststandby
		.set noreorder
sys_poststandby:
		move	k1, ra
#ifdef _M3383_01V01_
		li	t0, 0xb8000438
		li	t1, 0x00060000		
		sw	t1, (t0)	
#endif
		jal		get_boot_cfg_addr
		nop
		move	k0, v0					# k0: address of "boot.cfg" data

		get_pan_hw_info a0, k0
		jal 	pan_hwscan_init
		li		a1, 0
		get_pan_hw_info a1, k0			# Set STANDBY to invalid status
		lhu		a0, 30(a1)
		jal 	pan_hwscan_gpio_set_bit
		li		a1, 0

		move	ra, k1
		jr		ra
		nop
		.set reorder
		.end sys_poststandby
		

#################################################################
#	fucntion name: init_gpio()
#	used register	t0,t1,t2
#	global used	
#################################################################	
		.globl	init_gpio
		.ent	init_gpio
init_gpio:
		.set	noreorder
        lui     t0, SYS_IC_NB_BASE_H
        lhu     t1, 2(t0)
        and     t1, 0xffff
##The M3281 is same as M3603
        li      t2, 0x3281
        beq     t2, t1, init_3281
        nop
        j       gpio_init_end
        nop
init_3281:
        li      t1, 0x1cca3000
        sw      t1, 0xa0(t0)    ##GPIO32~GPIO63
gpio_init_end:        
		jr		ra
		nop
		.set	reorder
		.end	init_gpio


		.globl	sys_standby_process
		.ent	sys_standby_process
sys_standby_process:		
		.set	noreorder
		mfc0	t0, C0_COUNT			# Check scan or not
		li		t1, (TIMER_COMPARE_1S>>8)	# 1/256 second per LED
		subu    t2, s4, t0
		bgtu	t2, t1, real_scan
		nop
		li		v0,0
		jr		ra
		nop
real_scan:
		addu	s4, t1					# 1/256 second per LED
		move	k0, ra

		jal		get_boot_cfg_addr
		nop
		move	k1, v0					# k1: address of "boot.cfg" data

		lb		t1, STBY_PAN_TYPE(k1)
		bne		t1, 1, 1f			# if not show time, jump to 1f
		nop
		
		gettimerdata	t0
		move		s6, t0
1:				
# We just display one LED each times, keeping show when exit function
		get_pan_hw_info a0, k1
		lw		t3, (a0)
		srl 	t0, t3, 8
		andi	t0, 0x0f				# Inc and get current COM number
		srl 	t2, s6, 24
		addi	t2, 1
		bne 	t2, t0, 1f
		nop
		move	t2, zero
1:
		sll 	s6, 8					# Set new LED ID
		srl 	s6, 8
		sll 	t0, t2, 24
		or		s6, t0
		settimerdata	s6
		sll 	t0, t2, 2				# Get current LED COM index
		li		t1, 0x0c
		subu	t1, t0
		bgez	t1, dot_pos 			# If dot position > 3, LED bitmap should be '.'
		li		t0, 12
		b		dot_end
		nop

dot_pos:
		srl 	t0, s6, t1
		andi	t0, 0x0f				# Get current LED bitmap offset
dot_end:
		get_led_array t4, k1
		addu	t1, t4, t0
		lbu 	a2, (t1)				# Get current LED bitmap

dot_set:
		srl 	t0, t3, 12				# Check the dot LED
		andi	t0, 0x0f
		bne 	t0, t2, 2f
		nop
#ifndef _M3383_01V01_	
		lb		t0, 12(t4)				# Get the ":" mask map
		srl 	t1, s6, 16
		and 	t0, t1
		xor 	a2, t0
#endif
2:
#ifdef _M3383_01V01_	
		li	t0, 0xb8000438
		lw	t4, (t0)
		li	t3, 0xFFFBFFFF
		and	t4, t4, t3		
		srl 	t1, s6, 16				# Get the ":" mask map		
		andi	t1, 0x01
		not	t1
		andi	t1, 0x01
		sll	t2, t1, 18		
		or	t2, t2, t4
		sw	t2, (t0)
#endif
		sll 	a2, 8
		or		a2, s8
		jal 	pan_hwscan_scan
		srl 	a1, s6, 24

## if invalid key, jump to 3f
		li		t0, PAN_KEY_INVALID
		beq		t0, v0, 3f
		nop	

		get_fp_power_key_num	t2, k1
check_pan_power_key:					
		get_fp_power_key t0, t2, k1 		# Check power on key
		beq 	t0, v0, get_pan_power_key
		nop
		beqz	t2, 3f
		nop
		b		check_pan_power_key
		addiu		t2, -1
get_pan_power_key:
		li		s8, 0xdeadbead			# Set the flag about time to REF
		jal 	exit_standby			# Power key press, exit standby
		nop
3:
		move	ra, k0
		jr		ra
		nop
		.set reorder
		.end sys_standby_process


		.globl	sys_standby_exception
		.ent	sys_standby_exception
sys_standby_exception:	
		.set	noreorder

		la		t1, 3f					# Running in cache
		sll 	t1, 4
		srl 	t1, 4
		lui 	t0, 0x8000
		or		t1, t0
		jr		t1
		nop

3:
		lui 	t1,SYS_IC_NB_BASE_H
		lw		t2,SYS_IC_NB_EISR(t1)
		li		t0, SYS_IC_SB_IRC_BITIE
		and 	 t3,t2,t0				# IR interrupt?
		bnez	 t3,2f
		nop
		
		li		s8, 0xdeadbeef			# Set the flag about enter IC stanby again
		jal 	exit_standby
		nop
2:
		
		jal 	get_ir					# Get IR code
		nop


## if invalid key, jump to 4f
		li		t0, 0
		move	v1, v0
		beq		t0, v1, 4f
		nop	
		
		jal		get_boot_cfg_addr		# v0: address of "boot.cfg" data
		nop

		get_ir_power_key_num	t2, v0
check_ir_power_key:				
		get_ir_power_key	t0, t2, v0	# Check POWER remote key code		
		beq 	v1, t0, get_ir_power_key
		nop
		beqz	t2, 4f
		nop
		b		check_ir_power_key
		addiu		t2, -1
get_ir_power_key:		
		li		s8, 0xdeadbead			# Set the flag about time to REF
		jal 	exit_standby
		nop
4:
		nop
					nop
		.set mips3
		eret
		.set mips1
		nop
		nop
		.set reorder
		.end sys_standby_exception
